#ifndef _POLYHEDRON_
#define _POLYHEDRON_

#include "../meshdef/cgaltypes.h"
#include "drawable.h"
#include <vector>

// A vertex base with a normal vector
template < class Refs > 
struct My_Vertex 
 : public CGAL::HalfedgeDS_vertex_base< Refs, CGAL::Tag_true, Point> 
{
   /// Vertex normal
   Vector normal;
   // Must also provide these constructors
   My_Vertex (const Point& p) : CGAL::HalfedgeDS_vertex_base< Refs, CGAL::Tag_true, Point> (p) {}; 
   My_Vertex () : CGAL::HalfedgeDS_vertex_base< Refs, CGAL::Tag_true, Point> () {}; 

};

// An items type using my vertex.
struct My_items : public CGAL::Polyhedron_items_3 {
    template < class Refs, class Traits>
    struct Vertex_wrapper {
        typedef typename Traits::Point_3 Point;
        typedef My_Vertex <Refs> Vertex;
    };
};

///  An extended polyhedron class.
///  . Has a bounding box 
///  . Normals
///  . Opengl drawing
///
class Polyhedron : public CGAL::Polyhedron_3<Kernel,My_items>, public Drawable  
{
    
    double minimumCos; ///< Used for vertex normal computations.
    
public:
    
    /// Computes face planes from 3 vertices
    void compute_facet_planes ();
    
    /// Computes a bounding box for the polyhedron
    void compute_box ();
    
    /// Computes a bounding box for the polyhedron
    void compute_vertex_normals ();

    /// Sets the vertex normal computation method
    /// @param minCos minimum cosine admitted between the normal of edge adjoining facets and
    /// in order to include it in the normal average. 1 means no vertex smoothing, while -1 means
    /// all face normals are used to smooth the vertex normal. 
    void normal_policy (double minCos = 1);

    /// Opengl drawing code.
    virtual void draw () const;
    
    /// Default constructor
    Polyhedron () : CGAL::Polyhedron_3<Kernel,My_items> () { minimumCos = -1; }
    
    /// Returns a collection of intersection points between the polyhedron 
    /// and the given ray. The points are stored in an arbitrary order into the vector
    /// @param ray The intersected ray.
    /// @return a vector of intersected points.
    std::vector<Point> intersect (const Ray& r) const;
	
    /// Reads an off model into a polyhedron data structure and returns it
    /// @param filename Name of the file containing model
    /// @return pointer to newly read model or 0 if unsuccessful
    static Polyhedron* load_off (const char * filename);            
};

typedef Polyhedron::Halfedge_handle Halfedge_handle;
typedef Polyhedron::Halfedge_const_handle Halfedge_const_handle;
typedef Polyhedron::Facet_iterator Facet_iterator;
typedef Polyhedron::Facet_const_iterator Facet_const_iterator;
typedef Polyhedron::Edge_iterator Edge_iterator;
typedef Polyhedron::Facet::Halfedge_around_facet_circulator Halfedge_around_facet_circulator;

#endif
